/*
============================================================================
 Name        : interface.cpp
 Author      : Jian
 Version     :
 Copyright   : Hesine
 Description : interface.cpp - source file
============================================================================
*/

// INCLUDE FILES

extern "C" {
#include "nmsJpegDefine.h"
} ;

#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <f32file.h>
#include <bautils.h>
#include <stringloader.h>
#include <sys\types.h>
#include <sys\time.h>
#include <netinet\in.h>
#include <aknutils.h>
#include <aknmessagequerydialog.h> 
#include <e32math.h>

#include <math.h>

static RFs* _fileFs = NULL ;

#define __ToPtrC16(s)        TPtrC16((const TUint16*)s, User::StringLength((const TUint16*)s))
#define __ToPtrC8(s)         TPtrC8((const TUint8*)s, User::StringLength((const TUint8*)s))
#define __ToPtrC8Data(d,m)   TPtrC8((const TUint8*)d, m)

#define __ToPtr8(s,m)  TPtr8((TUint8*)s, m)
#define __ToPtr16(s,m)  TPtr16((TUint16*)s, m)
#define LogLeaveIfError User::LeaveIfError

static TBool _checkString(const char* aUtf8)
{
    __NMS_ASSERT_DEFENSE(aUtf8, return EFalse) ;
    __NMS_ASSERT_DEFENSE(strlen(aUtf8) <= 256, return EFalse) ;
    return ETrue ;
}

static TBool _checkString(const WCHAR* aUnicode)
{
    __NMS_ASSERT_DEFENSE(aUnicode, return EFalse) ;
    __NMS_ASSERT_DEFENSE(((((TUint)aUnicode) % 2) == 0), return EFalse) ;
    __NMS_ASSERT_DEFENSE(User::StringLength(aUnicode) <= 256, return EFalse) ;
    return ETrue ;
}


#define ENGINE_LOG0(a)
#define ENGINE_LOG1(a, b)
#define ENGINE_LOG2(a, b, c)
#define ENGINE_LOG3(a, b, c, d)

void* nmsMallocL(UINT32 size)
{
    void* ret = malloc(size) ;
    __NMS_ASSERT_DEFENSE(ret, ENGINE_LOG1(_L("nmsMallocL error size = %d"), size) ; return NULL) ;
    memset(ret, 0xCC, size) ;
    // memset(ret, 0, size) ;
    return ret;
}

void nmsFreeL(void* pMem)
{
    free(pMem) ;
}

static TBool _initFs()
{
    TRAPD(
        err,
        _fileFs = new(ELeave) RFs ;
    LogLeaveIfError(_fileFs->Connect());
    LogLeaveIfError(_fileFs->ShareAuto()) ;
    ) ;

    if (err != KErrNone)
    {
        ENGINE_LOG0(_L("Wow, that crazy : We can't init a RFs data handle!!!")) ;
        return EFalse ;
    }

    return ETrue ;
}

static TBool _createFolder(const TDesC& aFolderName)
{
    TInt err = _fileFs->MkDirAll(aFolderName) ;
    if (err != KErrNone)
    {
        ENGINE_LOG2(_L("_createFolder create the folder %S error = %d"), &aFolderName, err) ;
    }

    return err == KErrNone ;
}


static HFILE _openFile(const TDesC& name, UINT32 flag)
{
    if (!_fileFs && !_initFs())
        return 0 ;

OpenAgain:

    TInt mode     = 0 ;
    TBool replace = EFalse ;

    if (flag == NMS_FS_CREATE || flag == NMS_FS_CREATE_ALWAYS)
    {
        mode = EFileRead | EFileWrite ;
        replace = ETrue ;
    }
    else if (flag == NMS_FS_READ)
    {
        mode = EFileRead ;
    }
    else if (flag == NMS_FS_READ_WRITE)
    {
        mode = EFileRead | EFileWrite ;
    }

    mode |= EFileShareAny;

    RFile* file = NULL ;
    TRAPD(
        err,
        file = new(ELeave) RFile ;
    CleanupStack::PushL(file) ;
    LogLeaveIfError(replace ? file->Replace(*_fileFs, name, mode) : file->Open(*_fileFs, name, mode)) ;
    CleanupStack::Pop(file) ;
    ) ;

    if (err != KErrNone)
    {
        ENGINE_LOG3(_L("_openFile open the file = %S flag = %d, error = %d"), &name, flag, err) ;

        if (err == KErrPathNotFound)
        {
            ENGINE_LOG0(_L("_openFile err is KErrPathNotFound, try to make directory")) ;
            TInt sep = name.LocateReverse('\\') ;

            if (!sep)
            {
                ENGINE_LOG0(_L("_openFile err is KErrPathNotFound, cant not find the '\' ")) ;
                goto OpenEnd ;
            }

            if (!_createFolder(name.Left(sep + 1)))
            {
                ENGINE_LOG0(_L("_openFile err is KErrPathNotFound, _createFolder error ")) ;
                goto OpenEnd ;
            }

            goto OpenAgain ;
        }
    }

OpenEnd:

    return (err == KErrNone) ? (HFILE)file : NULL ;
}


HFILE nmsFsOpenW(WCHAR *nameW, UINT32 flag)
{
    __NMS_ASSERT_DEFENSE(_checkString(nameW), return 0) ;

    return _openFile(__ToPtrC16(nameW), flag) ;
}

int nmsFsRead(HFILE hFile, void *pData, int nLen, int *read)
{
    if (nLen == 0) {
        if (read) *read = 0 ;
        return 0 ;
    }

    if (!(hFile && pData && nLen > 0))
    {
        ENGINE_LOG3(_L("nmsFsRead argu is error hFile = %d, pData = %d, nLen = %d"), hFile, pData, nLen) ;
        return 0 ;
    }

    RFile* file = (RFile*)hFile ;

    TPtr8 ptr = __ToPtr8(pData, nLen) ;

    if (file->Read(ptr) != KErrNone)
    {
        if (read) *read = 0;
        return 0 ;
    }

    if (read) *read = ptr.Length();
    return ptr.Length();
}

int nmsFsWrite(HFILE hFile, void *pData, int nLen, int *written)
{
    if (nLen == 0) {
        if (written) *written = 0 ;
        return 0 ;
    }

    __NMS_ASSERT_DEFENSE(hFile && pData && nLen > 0, return 0) ;

    RFile* file = (RFile*)hFile ;

    if (file->Write(__ToPtrC8Data(pData, nLen)) != KErrNone)
    {
        if (written) *written = 0 ;
        return 0 ;
    }

    if (written) *written = nLen ;
    return nLen ;

}

int nmsFsSeek(HFILE hFile, int offset, int Whence)
{
    __NMS_ASSERT_DEFENSE(hFile, return -1) ;

    RFile* file = (RFile*)hFile ;

    TSeek mode = ESeekStart;
    if (Whence == NMS_FS_FILE_CURRENT)  mode = ESeekCurrent ;
    else if (Whence == NMS_FS_FILE_END) mode = ESeekEnd ;

    TInt pos     = offset ;
    TInt errCode = KErrNone ;
    if ((errCode = file->Seek(mode, pos)) != KErrNone)
    {
        ENGINE_LOG2(_L("nmsFsSeek mode = %d, error = %d"), Whence, errCode) ;
        pos = -1 ;
    }

    TInt size = 0 ;
    if (file->Size(size) == KErrNone && pos > size)
    {
        ENGINE_LOG2(_L("nmsFsSeek seek position = %d is bigger than file size = %d"), pos, size) ;
        file->SetSize(pos + 1) ;
    }

    return pos ;
}

int nmsFsTruncate(HFILE hFile, int size)
{
    __NMS_ASSERT_DEFENSE(hFile, return -1) ;

    RFile* file = (RFile*)hFile ;

    TInt errCode = KErrNone ;
    if ((errCode = file->SetSize(size)) != KErrNone)
    {
        ENGINE_LOG1(_L("nmsFsTruncate error = %d"), errCode) ;
        return -1 ;
    }

    return 0 ;
}

int nmsFsFlush(HFILE hFile)
{
    __NMS_ASSERT_DEFENSE(hFile, return -1) ;

    RFile* file = (RFile*)hFile ;
    file->Flush() ;
    return 0 ;
}

void nmsFsClose(HFILE hFile)
{
    __NMS_ASSERT_DEFENSE(hFile, return) ;

    RFile* file = (RFile*)hFile ;
    file->Close() ;
    delete file ;
}

int nmsFsCopyW(WCHAR *srcName, WCHAR *desName)
{
    __NMS_ASSERT_DEFENSE(_checkString(srcName), return -1) ;
    __NMS_ASSERT_DEFENSE(_checkString(desName), return -1) ;

    TPtrC src(__ToPtrC16(srcName)) ;
    TPtrC desc(__ToPtrC16(desName)) ;

    TInt ret = 0 ;
    TInt errCode = BaflUtils::CopyFile(*_fileFs, src, desc) ;

    if (errCode != KErrNone)
    {
        ret = -1;
        ENGINE_LOG3(_L("nmsFsCopyW source name = %S, dest name = %S error = %d"), &src, &desc, errCode) ;
    }

    return ret ;
}

int nmsFsGetFileSizeWithNameW(WCHAR *pNameW, int *size)
{
    if (!_fileFs && !_initFs())
        return 0 ;

    __NMS_ASSERT_DEFENSE(_checkString(pNameW), return 0) ;

    TInt fileSize = 0 ;
    TEntry entry;
    if (_fileFs->Entry(__ToPtrC16(pNameW), entry) == KErrNone)
        fileSize = entry.iSize ;

    if (size) *size = fileSize ;
    return fileSize;
}

int nmsStrCaseCmp(char *src, char *des)
{
    return strcasecmp(src, des) ;
}


static int	dd_vsnprintf(char* buffer, size_t buf_size, const char* format, va_list ap);       

static int	dd_snprintf(char* buffer, size_t bufsize, const char* format, ...)
{
    va_list	ap ;	
    int bytes = 0 ;
    va_start(ap, format);
    bytes = dd_vsnprintf(buffer, bufsize, format, ap);
    va_end(ap);
    return (bytes);
}

static int                                 /* O - Number of bytes formatted */
dd_vsnprintf(char       *buffer,    /* O - Output buffer */
             size_t     bufsize,    /* O - Size of output buffer */
             const char *format,    /* I - Printf-style format string */
             va_list    ap)         /* I - Pointer to additional arguments */
{
    char *bufptr,		/* Pointer to position in buffer */
         *bufend,		/* Pointer to end of buffer */
         sign,			/* Sign of format width */
         size,			/* Size character (h, l, L) */
         type;			/* Format type character */
    int  width,			/* Width of field */
         prec;          /* Number of characters of precision */
    char tformat[100],  /* Temporary format string for sprintf() */
        *tptr,          /* Pointer into temporary format */
        temp[1024];     /* Buffer for formatted numbers */
    char		*s;     /* Pointer to string */
    int		slen;       /* Length of string */
    int		bytes;      /* Total number of bytes needed */


    /*
    * Loop through the format string, formatting as needed...
    */

    bufptr = buffer;
    bufend = buffer + bufsize - 1;
    bytes  = 0;

    while (*format)
    {
        if (*format == '%')
        {
            tptr = tformat;
            *tptr++ = *format++;

            if (*format == '%')
            {
                if (bufptr && bufptr < bufend) *bufptr++ = *format;
                bytes ++;
                format ++;
                continue;
            }
            else if (strchr(" -+#\'", *format))
            {
                *tptr++ = *format;
                sign = *format++;
            }
            else
                sign = 0;

            if (*format == '*')
            {
                /*
                * Get width from argument...
                */

                format ++;
                width = va_arg(ap, int);

                dd_snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
                tptr += strlen(tptr);
            }
            else
            {
                width = 0;

                while (isdigit(*format & 255))
                {
                    if (tptr < (tformat + sizeof(tformat) - 1))
                        *tptr++ = *format;

                    width = width * 10 + *format++ - '0';
                }
            }

            if (*format == '.')
            {
                if (tptr < (tformat + sizeof(tformat) - 1))
                    *tptr++ = *format;

                format ++;

                if (*format == '*')
                {
                    /*
                    * Get precision from argument...
                    */

                    format ++;
                    prec = va_arg(ap, int);

                    dd_snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
                    tptr += strlen(tptr);
                }
                else
                {
                    prec = 0;

                    while (isdigit(*format & 255))
                    {
                        if (tptr < (tformat + sizeof(tformat) - 1))
                            *tptr++ = *format;

                        prec = prec * 10 + *format++ - '0';
                    }
                }
            }
            else
                prec = -1;

            if (*format == 'l' && format[1] == 'l')
            {
                size = 'L';

                if (tptr < (tformat + sizeof(tformat) - 2))
                {
                    *tptr++ = 'l';
                    *tptr++ = 'l';
                }

                format += 2;
            }
            else if (*format == 'h' || *format == 'l' || *format == 'L')
            {
                if (tptr < (tformat + sizeof(tformat) - 1))
                    *tptr++ = *format;

                size = *format++;
            }

            if (!*format)
                break;

            if (tptr < (tformat + sizeof(tformat) - 1))
                *tptr++ = *format;

            type  = *format++;
            *tptr = '\0';

            switch (type)
            {
            case 'E' : /* Floating point formats */
            case 'G' :
            case 'e' :
            case 'f' :
            case 'g' :
                if ((width + 2) > sizeof(temp))
                    break;

                sprintf(temp, tformat, va_arg(ap, double));

                bytes += strlen(temp);

                if (bufptr)
                {
                    if ((bufptr + strlen(temp)) > bufend)
                    {
                        strncpy(bufptr, temp, (size_t)(bufend - bufptr));
                        bufptr = bufend;
                    }
                    else
                    {
                        strcpy(bufptr, temp);
                        bufptr += strlen(temp);
                    }
                }
                break;

            case 'B' : /* Integer formats */
            case 'X' :
            case 'b' :
            case 'd' :
            case 'i' :
            case 'o' :
            case 'u' :
            case 'x' :
                if ((width + 2) > sizeof(temp))
                    break;
                sprintf(temp, tformat, va_arg(ap, int));

                bytes += strlen(temp);

                if (bufptr)
                {
                    if ((bufptr + strlen(temp)) > bufend)
                    {
                        strncpy(bufptr, temp, (size_t)(bufend - bufptr));
                        bufptr = bufend;
                    }
                    else
                    {
                        strcpy(bufptr, temp);
                        bufptr += strlen(temp);
                    }
                }
                break;

            case 'p' : /* Pointer value */
                if ((width + 2) > sizeof(temp))
                    break;

                sprintf(temp, tformat, va_arg(ap, void *));

                bytes += strlen(temp);

                if (bufptr)
                {
                    if ((bufptr + strlen(temp)) > bufend)
                    {
                        strncpy(bufptr, temp, (size_t)(bufend - bufptr));
                        bufptr = bufend;
                    }
                    else
                    {
                        strcpy(bufptr, temp);
                        bufptr += strlen(temp);
                    }
                }
                break;

            case 'c' : /* Character or character array */
                bytes += width;

                if (bufptr)
                {
                    if (width <= 1)
                        *bufptr++ = va_arg(ap, int);
                    else
                    {
                        if ((bufptr + width) > bufend)
                            width = bufend - bufptr;

                        memcpy(bufptr, va_arg(ap, char *), (size_t)width);
                        bufptr += width;
                    }
                }
                break;

            case 's' : /* String */
                if ((s = va_arg(ap, char *)) == NULL)
                    s = "(null)";
                
                slen = strlen(s);
                if (slen > width && prec != width)
                    width = slen;

                bytes += width;

                if (bufptr)
                {
                    if ((bufptr + width) > bufend)
                        width = bufend - bufptr;

                    if (slen > width)
                        slen = width;

                    if (sign == '-')
                    {
                        strncpy(bufptr, s, (size_t)slen);
                        memset(bufptr + slen, ' ', (size_t)(width - slen));
                    }
                    else
                    {
                        memset(bufptr, ' ', (size_t)(width - slen));
                        strncpy(bufptr + width - slen, s, (size_t)slen);
                    }

                    bufptr += width;
                }
                break;

            case 'n' : /* Output number of chars so far */
                *(va_arg(ap, int *)) = bytes;
                break;
            }
        }
        else
        {
            bytes ++;

            if (bufptr && bufptr < bufend)
                *bufptr++ = *format;

            format ++;
        }
    }

    /*
    * Nul-terminate the string and return the number of characters needed.
    */

    *bufptr = '\0';

    return (bytes);
}

#define __MAX_LOG_BUFFER  512 
static HFILE _logFile = 0 ;

void _nprintf(char *format,...) 
{
    va_list arg;
    int     dummyLen = 0 ;
    char    buffer[__MAX_LOG_BUFFER + 1] = {0};

    if (_logFile == 0) {
        _logFile = nmsFsOpenW((WCHAR*)L"C:\\data\\jpeg.log", NMS_FS_READ_WRITE) ;

        if (_logFile == 0) 
            _logFile = nmsFsOpenW((WCHAR*)L"C:\\data\\jpeg.log", NMS_FS_CREATE) ;
        
        if (_logFile == 0)  return ;

        nmsFsSeek(_logFile, 0, NMS_FS_FILE_END) ;
    }        
    
    va_start (arg, format);
    dd_vsnprintf(buffer, __MAX_LOG_BUFFER, format, arg) ;
    va_end (arg);

    nmsFsWrite(_logFile, buffer, strlen(buffer), &dummyLen) ;
    nmsFsWrite(_logFile, (void*)"\r\n", 2, &dummyLen) ;
}

int nmsUcs2StrCaseCmp(unsigned short *s1, unsigned short *s2)
{
    return 1 ;
}

int nmsUcs2Strlen (unsigned short *start)
{
    int len = 0;
    char *p = 0;

    if(!start)
        return 0;

    p = (char *)start;

    while ( (*p != 0) || (*(p+1) !=0) ) {
        p += 2;
        len++;
    }

    return len;
}

void nmsUcs2Cpy (void *dest, void *src) 
{
    unsigned char *to, *from;

    to = (unsigned char *)dest;
    from = (unsigned char *)src;

    while ( *from != 0 || *(from+1) != 0) {
        *to = *from;
        to++; from++;

        *to = *from;
        to++; from++;
    }

    *to=0; to++;
    *to=0;
}


void nmsAssertPainc(const char* aFileName, int line) 
{
    TPtrC8 filePtr((TUint8*)aFileName, strlen(aFileName)) ;
    _LIT8(formatStr, "Assert in File : %S, Line: %d") ;

    HBufC8* str = HBufC8::NewLC(filePtr.Length() + formatStr().Length() + 11) ;
    str->Des().Format(formatStr, &filePtr, line) ;

    HBufC* strUni = HBufC::NewLC(str->Length()) ;
    strUni->Des().Copy(*str) ;

    CAknMessageQueryDialog* dlg = new (ELeave)CAknMessageQueryDialog(); 
    dlg->PrepareLC(R_AVKON_MESSAGE_QUERY_DIALOG); 
    dlg->SetHeaderTextL(_L("Assert")) ;
    dlg->SetMessageTextL(*strUni);

    if (dlg->RunLD() == EAknSoftkeyOk)
    {
        User::Exit(0) ;
    }

    CleanupStack::PopAndDestroy(2) ;
}


UINT32 nmsGetSystemTime( )
{
    int t = time(NULL) ;
    struct timeval systemTime;
    gettimeofday(&systemTime, 0);
    return systemTime.tv_sec;
}


int nmsRandom() 
{
    return Math::Random() ;
}

int nmsFsTell(HFILE hFile)
{
    __NMS_ASSERT_DEFENSE(hFile, return 0) ;

    RFile* file = (RFile*)hFile ;
    int pos = 0 ;
    file->Seek(ESeekCurrent, pos) ;
    return pos ;
}

/* End of File */
